include Java

Dep=['javax.mail', 'javax.mail.internet', 'java.io', 'java.security', 'java.math']
JFile=java.io.File
JFOStream=java.io.FileOutputStream
JDigest=java.security.MessageDigest

class AppendResult
  attr_reader :md5, :size
  def initialize(md5, size)
    @md5=md5
    @size=size
  end
end

class MboxHandler
  Dep.each { |d| include_package(d) }

  def initialize(path)
    @path=path
    @tmp= Settings[:output]+'tmp.mbox'
    clear_tmp
    @md5=JDigest.getInstance("MD5")
  end
  
=begin
  Appends message to the mbox file specified by @path
  returns the md5 of the saved message and its size on the disk
=end
  def append_message(message)
    write_to_tmp(message)
    @md5.reset
    from = "From "+Time.now.to_s
    File.open(@path, 'a') do |file|
      file.puts from
      File.open(@tmp, 'r') do |tmp|
        while (line = tmp.gets)
          esc_from_line = line.gsub('From', '>From') # escaping message from
          @md5.update(esc_from_line.to_java_bytes, 0, esc_from_line.length)
          file.puts esc_from_line
        end
      end
    end
    return AppendResult.new(md5_to_s(@md5), File.size(@tmp)+from.length)
  ensure
    clear_tmp 
  end

  def write_to_tmp(message)
    jtmp = JFile.new(@tmp)
    output=JFOStream.new(jtmp)
    message.writeTo(output)
  ensure
    output.close
  end
  
=begin 
    This methods verifies the i message that was persisted in the @path file
   according to an MD5 value
=end
  def verify_message(m_nr, other_md5)
    message_nr=0
    @md5.reset
    f=File.new(@path)
    while (line=f.gets)
      @md5.update(line.to_java_bytes, 0, line.length) if message_nr==m_nr
      message_nr+=1 if line=~/^From*/
    end
    return (md5_to_s(@md5)<=>other_md5)==0
  end

  # This method clears up the i message that was saved
  def clear_last_message(size)
    File.open(@path,'r+').truncate(File.size(@path)-size)
  end

  def count_messages
    return IO.readlines(@path).inject(0) { |c,line| c+=1 if line=~/^From*/;c}
  end

  private
  def clear_tmp
    if File.exist?(@tmp)
      FileUtils.rm @tmp
    end
  end

  def md5_to_s(md5)
    BigInteger.new(1, md5.digest()).toString(16)
  end
end


